package com.kira.scaffoldmvc.Strategy;

import org.springframework.beans.factory.InitializingBean;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

/**
 * 单实例 Bean 容器，用于管理每个键对应单个策略 Bean 的场景
 * 继承自 DefaultBeanContainer，泛型参数 K 为键类型，V 为策略 Bean 类型且需实现 IBeanType 接口
 * 容器中存储的每个键对应唯一的策略 Bean，若存在重复键会被覆盖
 */
public abstract class SingleBeanContainer<K, V extends IBeanType<K>> extends DefaultBeanContainer<K, V> implements InitializingBean {

    /**
     * 创建 Bean 映射关系的核心方法（由父类 DefaultBeanContainer 调用）
     * 实现逻辑：
     * 1. 从 Spring 容器中获取所有指定类型的策略 Bean
     * 2. 按 beanType() 方法的返回值作为键，将 Bean 存入 Map
     * 3. 若存在相同键的 Bean，后处理的 Bean 会覆盖先处理的 Bean
     * @return 键为 K、值为 V 的映射表
     */
    @Override
    public Map<K, V> createBeanMap() {
        // 获取 Spring 容器中所有类型为 this.type 的 Bean 实例（值类型为 V）
        Collection<V> beans = (Collection<V>) this.applicationContext.getBeansOfType(this.type).values();

        // 使用 Stream API 将 Bean 按 beanType() 分组到 Map 中
        return beans.stream()
                // 过滤掉 beanType() 返回 null 的无效 Bean
                .filter(bean -> bean.beanType() != null)
                // 归约操作：将每个 Bean 按 beanType() 作为键存入 Map
                .reduce(new HashMap<>(8), (beansMap, bean) -> {
                    // 若存在相同键的 Bean，后处理的 Bean 会覆盖先处理的 Bean
                    beansMap.put(bean.beanType(), bean);
                    return beansMap;
                }, (a, b) -> a); // 并行流时的合并逻辑（此处无实际作用）
    }
}